package com.starry.module.system.core.oauth2.authorization.grant;

import com.starry.core.common.domain.R;
import com.starry.core.ip.core.utils.IPUtils;
import com.starry.core.security.context.SecurityInfoContext;
import com.starry.core.security.domain.BaseUser;
import com.starry.module.system.api.oauth2.domain.vo.CustomGranLoginSuccessVo;
import com.starry.module.system.api.user.domain.qo.SysUserLoginInfoQo;
import com.starry.module.system.core.oauth2.authorization.utils.SecurityUtils;
import com.starry.module.system.core.user.service.SysUserService;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationToken;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import java.io.IOException;
import java.time.LocalDateTime;

/**
 * @Description 自定义grant认证成功处理器
 * @Author xiaoke
 */
public class CustomGrantAccessTokenResponseHandler implements AuthenticationSuccessHandler {
    private final SysUserService sysUserService;

    public CustomGrantAccessTokenResponseHandler(SysUserService sysUserService) {
        this.sysUserService = sysUserService;
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        CustomGranLoginSuccessVo vo = new CustomGranLoginSuccessVo();
        R<CustomGranLoginSuccessVo> result = new R<>();

        String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);

        if (authentication instanceof OAuth2AccessTokenAuthenticationToken token) {
            vo.setAccessToken(token.getAccessToken().getTokenValue());
            vo.setScope(token.getAccessToken().getScopes());
            vo.setTokenType(token.getAccessToken().getTokenType().getValue());
            if (token.getRefreshToken() != null) {
                vo.setRefreshToken(token.getRefreshToken().getTokenValue());
            }
            result.setCode(HttpStatus.OK.value());
            result.setSuccess(true);
            result.setMsg("认证成功");
            result.setData(vo);
        } else {
            result.setSuccess(false);
            result.setMsg("认证失败");
            result.setCode(HttpStatus.BAD_REQUEST.value());
        }

        // 刷新Token的时候不更新用户登陆信息
        if (!grantType.equals("refresh_token")) {
            BaseUser loginUser = SecurityInfoContext.getLoginUser();
            SysUserLoginInfoQo loginInfoQo = new SysUserLoginInfoQo();
            loginInfoQo.setId(loginUser.getId());
            loginInfoQo.setLoginDate(LocalDateTime.now());
            loginInfoQo.setLoginIp(IPUtils.getIpAddr(request));
            try {
                loginInfoQo.setIpCity(IPUtils.getArea(loginInfoQo.getLoginIp()).getName());
            } catch (Exception ignored) {
            }
            sysUserService.updateLoginInfo(loginInfoQo);
        }

        SecurityUtils.writeResponse(result, response);
    }
}
